Skip to content

feat: add support for OpenAI SDK v5 #644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

hmnzr
Copy link

@hmnzr hmnzr commented Aug 12, 2025

Closes #642

After bumping the SDK to v5, we've stopped receiving traces.

However, the new SDK seems to be backward compatible for chat completions and completions. I have tested a local build with [email protected] and it's still working fine.


Important

Add support for OpenAI SDK v5 in instrumentation.ts and types.ts, ensuring backward compatibility.

  • Behavior:
    • Updates InstrumentationNodeModuleDefinition in instrumentation.ts to support OpenAI SDK versions ">=3.1.0 <6".
    • Adds OpenAIVersion type in types.ts to include "v5".
  • Functions:
    • Updates patchOpenAI() and _wrapPromise() in instrumentation.ts to use OpenAIVersion type for version handling.

This description was created by Ellipsis for 3e0b7b1. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • New Features
    • Broader OpenAI SDK compatibility (supports newer v5 series) and a new public version type to select SDK versions.
  • Bug Fixes
    • Improved streaming behavior and more precise handling of tool/function calls in streamed assistant responses.
  • Chores
    • Developer tooling updated to a newer OpenAI SDK for testing and development.

@CLAassistant
Copy link

CLAassistant commented Aug 12, 2025

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to 3e0b7b1 in 55 seconds. Click for details.
  • Reviewed 52 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 5 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/instrumentation-openai/src/instrumentation.ts:28
  • Draft comment:
    Import updated to include OpenAIVersion for type safety.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, stating that an import was updated for type safety. It does not provide any actionable feedback or suggestions for improvement. According to the rules, purely informative comments should be removed.
2. packages/instrumentation-openai/src/instrumentation.ts:121
  • Draft comment:
    Updated version range to [">=3.1.0 <6"] to support OpenAI SDK v5.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, as it only states what was done without providing any actionable feedback or suggestions. It doesn't ask for confirmation or suggest any changes.
3. packages/instrumentation-openai/src/instrumentation.ts:213
  • Draft comment:
    Changed patchOpenAI parameter type to OpenAIVersion for clarity and support for v5.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, explaining a change that was made. It does not provide a suggestion, ask for confirmation, or point out a potential issue. It violates the rule against making purely informative comments.
4. packages/instrumentation-openai/src/instrumentation.ts:602
  • Draft comment:
    Updated _wrapPromise version parameter to use OpenAIVersion, ensuring v5 is handled like v4.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, describing a change made in the code without providing any actionable feedback or suggestions. It does not ask for confirmation or suggest improvements, nor does it point out any potential issues with the change.
5. packages/instrumentation-openai/src/types.ts:3
  • Draft comment:
    Extended OpenAIVersion union to include "v5", ensuring proper type support.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, stating what was done without providing any actionable feedback or suggestions. It doesn't ask for confirmation or suggest any improvements.

Workflow ID: wflow_bm8yv8lJH3cH4kRw

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

coderabbitai bot commented Aug 12, 2025

Walkthrough

Expands OpenAI SDK compatibility from ">=3.1.0 <5" to ">=3.1.0 <6", exports OpenAIVersion = "v3" | "v4" | "v5", updates internal signatures to accept OpenAIVersion, and replaces local APIPromise usage with openai.APIPromise; runtime branching still distinguishes v3 from other versions.

Changes

Cohort / File(s) Summary
OpenAI instrumentation logic
packages/instrumentation-openai/src/instrumentation.ts
Imports OpenAIVersion; expands supported SDK range to <6; updates patchOpenAI and _wrapPromise signatures to accept version: OpenAIVersion; replaces APIPromise type usage with openai.APIPromise<T>; runtime still branches on version === "v3"; adjusts tool and streaming handling (tool.type checks, streaming refusal field, local currentToolCall usage).
Types
packages/instrumentation-openai/src/types.ts
Adds exported type `OpenAIVersion = "v3"
DevDependencies
packages/instrumentation-openai/package.json
Bumps devDependency openai from 4.38.3 to 5.12.2 (align tests/dev with SDK v5).

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Instrumentation as instrumentation.ts
  participant Wrapper as _wrapPromise
  Caller->>Instrumentation: call patchOpenAI(type, version: OpenAIVersion)
  Instrumentation->>Wrapper: _wrapPromise(type, version, span, promise)
  alt version === "v3"
    Wrapper->>Wrapper: apply v3-specific handling
  else v4 or v5
    Wrapper->>Wrapper: apply non-v3 (shared) handling
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Assessment against linked issues

Objective Addressed Explanation
Support OpenAI SDK v5 (#642)

Poem

I thump my paws: v5 hops in bright, 🥕
Types snugly bound beneath the moonlight.
V3 takes one path, the others share two,
I twitch my nose and patch on through.
Hop, instrumenters, the rabbit coded true.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Member

@nirga nirga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @hmnzr! Can you sign the CLA and update package.json with OpenAI v6 - this will trigger the tests with the new version so we can see that everything indeed works (I'm not sure it will though)

@hmnzr
Copy link
Author

hmnzr commented Aug 12, 2025

@nirga I did sign it but it still haven't refreshed the status.

As for bumping the version, you mean the dev dependency or manually bump the package.json version?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/instrumentation-openai/src/instrumentation.ts (1)

216-216: Clarify defaulting behavior: v5 currently shares the v4 code path

To avoid confusion for future readers, annotate that v5 intentionally uses the non-v3 branch.

Apply this minimal inline comment:

-    version: OpenAIVersion = "v4",
+    version: OpenAIVersion = "v4", // v5 currently shares v4 behavior
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b43eaaf and 3e0b7b1.

📒 Files selected for processing (2)
  • packages/instrumentation-openai/src/instrumentation.ts (4 hunks)
  • packages/instrumentation-openai/src/types.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/instrumentation-openai/src/instrumentation.ts (1)
packages/instrumentation-openai/src/types.ts (1)
  • OpenAIVersion (3-3)
🔇 Additional comments (3)
packages/instrumentation-openai/src/types.ts (1)

3-3: OpenAIVersion union extended to include v5 — looks good

This aligns the public type surface with the widened SDK support.

packages/instrumentation-openai/src/instrumentation.ts (2)

28-28: Type import update is consistent with the new OpenAIVersion

Importing the union from a single source keeps version handling consistent.


605-605: Confirmed: APIPromise._thenUnwrap remains stable in v5, returning the unwrapped entity
We’ve verified that in OpenAI Node SDK v5 (5.0.0-alpha) the private-style helper _thenUnwrap still exists and continues to resolve to the parsed data payload (not an OpenAIResponse wrapper), matching v4 behavior.

• Note that _thenUnwrap is not part of the public API and may change without notice.
• For guaranteed stability, you can use await (which yields the parsed entity), or the new public methods asResponse() (to get the raw Response) and withResponse() (to get both { data, response }).

@@ -119,7 +119,7 @@ export class OpenAIInstrumentation extends InstrumentationBase {
protected init(): InstrumentationModuleDefinition {
const module = new InstrumentationNodeModuleDefinition(
"openai",
[">=3.1.0 <5"],
[">=3.1.0 <6"],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Widened module semver range to >=3.1.0 <6 — verify repo-wide alignment (docs, deps, tests)

Ensure we don’t have stale references to "<5" elsewhere and that CI/tests cover v5.

Run the following to find and update any lingering constraints and to surface any openai dependency ranges:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for legacy range '>=3.1.0 <5' across the repo..."
rg -n ">=3\.1\.0\s*<5" || true

echo
echo "Searching for 'openai' version constraints in package.json files..."
fd -a package.json | while read -r f; do
  hits=$(rg -n '"openai"\s*:\s*"[^\"]+"' "$f" || true)
  if [[ -n "$hits" ]]; then
    echo "$f"
    echo "$hits"
    echo
  fi
done

echo "Checking docs/workflows for hardcoded SDK support statements..."
rg -n "(OpenAI SDK|openai@|>=3\.1\.0\s*<5|<5)" --glob '*.md' --glob '.github/**/*.yml' || true

Length of output: 5204


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspecting instrumentation-openai package.json for openai dependency entries..."
grep -R '"openai"' -n packages/instrumentation-openai/package.json || true

Length of output: 300


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Displaying lines 40-80 from packages/instrumentation-openai/package.json to inspect dependency sections..."
sed -n '40,80p' packages/instrumentation-openai/package.json

Length of output: 1173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Listing all GitHub workflow files:"
fd -a -e yml .github/workflows

echo
echo "Scanning workflows for 'openai' references:"
rg -n "openai" .github/workflows

echo
echo "Scanning workflows for matrix definitions:"
rg -n "matrix" .github/workflows

Length of output: 505


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspecting peerDependencies in instrumentation-openai package.json..."
grep -R '"peerDependencies"' -n packages/instrumentation-openai/package.json || true
sed -n '1,39p' packages/instrumentation-openai/package.json

echo
echo "Checking for GitHub workflow files..."
if [ -d ".github/workflows" ]; then
  find .github/workflows -type f -name '*.yml'
else
  echo ".github/workflows directory not found"
fi

echo
echo "Scanning workflows for 'matrix' or 'openai' references..."
grep -R -n -E 'matrix|openai' .github/workflows || true

Length of output: 1578


Ensure OpenAI v5 is covered in tests, deps, and CI

  • ✅ No legacy >=3.1.0 <5 ranges found in code or docs.
  • packages/instrumentation-openai/package.json
    • devDependencies still pin "openai": "4.38.3" (tests only exercise v4).
    • No peerDependencies entry for openai—add:
      "peerDependencies": {
        "openai": ">=3.1.0 <6"
      }
  • CI workflows (.github/workflows/ci.yml) have no matrix for multiple openai versions.
  • After adding peerDeps and CI matrix, update devDependency or use npm install openai@${{ matrix.version }} in the test job.
🤖 Prompt for AI Agents
In packages/instrumentation-openai/src/instrumentation.ts around line 122, tests
and package metadata don’t cover OpenAI v5: add a peerDependencies entry in
packages/instrumentation-openai/package.json with "openai": ">=3.1.0 <6"; stop
pinning openai in devDependencies (or update it to a range that includes v5) so
local dev isn’t the only source of truth; modify .github/workflows/ci.yml to add
a job matrix for openai versions (at minimum 4.x and 5.x) and in the test job
run npm install openai@${{ matrix.version }} (or use npm ci after adjusting
package.json) so CI actually runs tests against both versions; ensure tests pass
with v5 and adjust any version-specific mocks or imports accordingly.

@nirga
Copy link
Member

nirga commented Aug 12, 2025

@hmnzr the dev dependency in the package.json

@hmnzr
Copy link
Author

hmnzr commented Aug 13, 2025

@nirga done!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3e0b7b1 and f020ac6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • packages/instrumentation-openai/package.json (1 hunks)

@@ -55,7 +55,7 @@
"@types/mocha": "^10.0.10",
"@types/node": "^24.0.15",
"mocha": "^11.7.1",
"openai": "4.38.3",
"openai": "5.12.2",
Copy link

@coderabbitai coderabbitai bot Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Use a caret range for devDependency and verify Node.js >= 18 in CI/tooling

Pinning openai to an exact version is inconsistent with the rest of devDependencies and prevents receiving compatible patch/minor updates within v5. Also, the OpenAI SDK v5 requires Node.js >= 18. Make sure your CI/tooling uses Node >= 18, otherwise installs/tests may fail even if this package’s engines allow >=14.

Apply this diff to align the semver policy:

-    "openai": "5.12.2",
+    "openai": "^5.12.2",

If you want to make the Node requirement explicit in this package to avoid confusion for contributors running tests locally, consider bumping the engines field (outside this hunk). Example:

{
  "engines": {
    "node": ">=18"
  }
}

Run this script to verify Node versions configured across the repo:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching engines declarations across package.json files..."
rg -n '"engines"\s*:\s*{' -A 3 package.json packages/**/package.json || true

echo
echo "Inspecting GitHub Actions node setup (if any)..."
if [ -d .github/workflows ]; then
  rg -n "setup-node" -A 8 .github/workflows || true
  rg -n "node-version" -A 2 .github/workflows || true
else
  echo "No .github/workflows directory found."
fi

echo
echo "Checking local Node version config files..."
for f in .nvmrc .tool-versions .node-version; do
  if [ -f "$f" ]; then
    echo "== $f =="
    cat "$f"
    echo
  fi
done

Length of output: 3790


Align openai to semver policy & confirm Node.js ≥18

  • In packages/instrumentation-openai/package.json, change the pinned openai devDependency to a caret range so that patch/minor updates within v5 are picked up.
  • CI already sources Node.js version from .nvmrc (currently “20”), so the OpenAI SDK v5 requirement (Node ≥18) is satisfied.
  • (Optional) To make the Node.js requirement explicit for local development, you can add an engines field to this package’s package.json:
--- a/packages/instrumentation-openai/package.json
+++ b/packages/instrumentation-openai/package.json
@@ devDependencies
-    "openai": "5.12.2",
+    "openai": "^5.12.2",

Optional engines snippet:

{
  "engines": {
    "node": ">=18"
  }
}
🤖 Prompt for AI Agents
In packages/instrumentation-openai/package.json around line 58, the
devDependency "openai" is pinned to an exact version ("5.12.2"); change it to a
caret range (e.g., "^5.12.2") so minor/patch updates within v5 are picked up,
and optionally add an "engines" field with "node": ">=18" to make the Node.js
requirement explicit for local development.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 @hmnzr

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@nirga
Copy link
Member

nirga commented Aug 13, 2025

Like I suspected @hmnzr - it requires some updates to the instrumentation code

@hmnzr
Copy link
Author

hmnzr commented Aug 14, 2025

@nirga adjusted but I see you work on the support internally already here #646

happy to close mine in that case

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/instrumentation-openai/src/instrumentation.ts (1)

118-126: Widened semver to >=3.1.0 <6 — LGTM; ensure metadata/CI also reflect v5 coverage

Change looks good here. Please make sure package metadata (peerDependencies) and CI test matrix also include openai v5 so we actually exercise these paths in CI. This was already raised earlier; echoing for alignment.

🧹 Nitpick comments (2)
packages/instrumentation-openai/src/instrumentation.ts (2)

28-28: Use type-only import to avoid runtime side-effects

These are types only; importing with import type prevents emitting a runtime import and is safer with TS configs like verbatimModuleSyntax.

Apply this diff:

-import { OpenAIVersion, OpenAIInstrumentationConfig } from "./types";
+import type { OpenAIVersion, OpenAIInstrumentationConfig } from "./types";

367-380: Guard against malformed tool entries

While the SDK should provide function when type === "function", a defensive check avoids runtime errors if inputs are malformed or come from mocks.

Apply this diff:

-          params.tools?.forEach((tool, index) => {
-            if (tool.type !== "function") {
-              return;
-            }
+          params.tools?.forEach((tool, index) => {
+            if (tool.type !== "function" || !tool.function) {
+              return;
+            }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f020ac6 and 2ece4a2.

📒 Files selected for processing (1)
  • packages/instrumentation-openai/src/instrumentation.ts (9 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/instrumentation-openai/src/instrumentation.ts (3)
packages/instrumentation-openai/src/types.ts (1)
  • OpenAIVersion (3-3)
packages/traceloop-sdk/src/lib/tracing/decorators.ts (1)
  • tool (276-282)
packages/ai-semantic-conventions/src/SemanticAttributes.ts (1)
  • SpanAttributes (17-59)
🔇 Additional comments (4)
packages/instrumentation-openai/src/instrumentation.ts (4)

213-216: Signature updated to use OpenAIVersion with sensible default — LGTM

The expanded version typing keeps the branching logic intact and future-proofs the signature.


403-421: Streaming APIPromise typing switch — LGTM

Using openai.APIPromise<Stream<...>> aligns with v4/v5 typing for streaming responses.


435-436: Initialize refusal field — LGTM

Pre-populating refusal: null matches v4/v5 object shape and avoids optional chaining later.


707-716: Span attributes for tool_calls gated by type — LGTM

Only emitting tool call attributes when type === "function" avoids mislabeling other tool types.

Comment on lines +484 to 502
const currentToolCall =
result.choices[0].message.tool_calls[toolCall.index];

if (toolCall.id) {
result.choices[0].message.tool_calls[toolCall.index].id +=
toolCall.id;
currentToolCall.id += toolCall.id;
}
if (toolCall.type) {
result.choices[0].message.tool_calls[toolCall.index].type +=
toolCall.type;
}
if (toolCall.function?.name) {
result.choices[0].message.tool_calls[
toolCall.index
].function.name += toolCall.function.name;
currentToolCall.type += toolCall.type;
}
if (toolCall.function?.arguments) {
result.choices[0].message.tool_calls[
toolCall.index
].function.arguments += toolCall.function.arguments;

if (currentToolCall.type === "function") {
if (toolCall.function?.name) {
currentToolCall.function.name += toolCall.function.name;
}
if (toolCall.function?.arguments) {
currentToolCall.function.arguments +=
toolCall.function.arguments;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: concatenating tool_call.id/type corrupts values; assign instead of appending

Using += for id and type will produce incorrect values (e.g., "functionfunction") and can break the subsequent currentToolCall.type === "function" check. IDs and types are not streamed token-by-token; assign them.

Apply this diff:

-            const currentToolCall =
-              result.choices[0].message.tool_calls[toolCall.index];
+            const currentToolCall =
+              result.choices[0].message.tool_calls[toolCall.index];

             if (toolCall.id) {
-              currentToolCall.id += toolCall.id;
+              currentToolCall.id = toolCall.id;
             }
             if (toolCall.type) {
-              currentToolCall.type += toolCall.type;
+              currentToolCall.type = toolCall.type;
             }

             if (currentToolCall.type === "function") {
               if (toolCall.function?.name) {
                 currentToolCall.function.name += toolCall.function.name;
               }
               if (toolCall.function?.arguments) {
                 currentToolCall.function.arguments +=
                   toolCall.function.arguments;
               }
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const currentToolCall =
result.choices[0].message.tool_calls[toolCall.index];
if (toolCall.id) {
result.choices[0].message.tool_calls[toolCall.index].id +=
toolCall.id;
currentToolCall.id += toolCall.id;
}
if (toolCall.type) {
result.choices[0].message.tool_calls[toolCall.index].type +=
toolCall.type;
}
if (toolCall.function?.name) {
result.choices[0].message.tool_calls[
toolCall.index
].function.name += toolCall.function.name;
currentToolCall.type += toolCall.type;
}
if (toolCall.function?.arguments) {
result.choices[0].message.tool_calls[
toolCall.index
].function.arguments += toolCall.function.arguments;
if (currentToolCall.type === "function") {
if (toolCall.function?.name) {
currentToolCall.function.name += toolCall.function.name;
}
if (toolCall.function?.arguments) {
currentToolCall.function.arguments +=
toolCall.function.arguments;
}
}
const currentToolCall =
result.choices[0].message.tool_calls[toolCall.index];
if (toolCall.id) {
currentToolCall.id = toolCall.id;
}
if (toolCall.type) {
currentToolCall.type = toolCall.type;
}
if (currentToolCall.type === "function") {
if (toolCall.function?.name) {
currentToolCall.function.name += toolCall.function.name;
}
if (toolCall.function?.arguments) {
currentToolCall.function.arguments +=
toolCall.function.arguments;
}
}
🤖 Prompt for AI Agents
In packages/instrumentation-openai/src/instrumentation.ts around lines 484 to
502, the code currently uses string concatenation (+=) when setting tool_call
fields which corrupts values (e.g., "functionfunction"); change the assignments
so you set values directly instead of appending: assign toolCall.id and
toolCall.type to currentToolCall.id and currentToolCall.type (use =), and
likewise assign function.name and function.arguments directly when
currentToolCall.type === "function", ensuring no concatenation occurs.

Comment on lines 604 to 611
private _wrapPromise<T>(
type: "chat" | "completion",
version: "v3" | "v4",
version: OpenAIVersion,
span: Span,
promise: APIPromise<T>,
): APIPromise<T> {
promise: openai.APIPromise<T>,
): openai.APIPromise<T> {
return promise._thenUnwrap((result) => {
if (version === "v3") {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Don’t rely on private _thenUnwrap; add fallback to .then for v3 compatibility and forward-compat

_thenUnwrap is an underscored, non-public helper on APIPromise (subject to change). For v3, the returned promise won’t have it at all. This can break instrumentation for v3 (and future v5 changes). Use .then when _thenUnwrap is unavailable.

Apply this diff:

-  ): openai.APIPromise<T> {
-    return promise._thenUnwrap((result) => {
+  ): openai.APIPromise<T> {
+    // Prefer the public .then; fall back to _thenUnwrap only if present (v4/v5 APIPromise).
+    const apiPromise: any = promise as any;
+    const chain =
+      typeof apiPromise._thenUnwrap === "function"
+        ? apiPromise._thenUnwrap.bind(apiPromise)
+        : apiPromise.then.bind(apiPromise);
+    return chain((result: any) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private _wrapPromise<T>(
type: "chat" | "completion",
version: "v3" | "v4",
version: OpenAIVersion,
span: Span,
promise: APIPromise<T>,
): APIPromise<T> {
promise: openai.APIPromise<T>,
): openai.APIPromise<T> {
return promise._thenUnwrap((result) => {
if (version === "v3") {
private _wrapPromise<T>(
type: "chat" | "completion",
version: OpenAIVersion,
span: Span,
promise: openai.APIPromise<T>,
): openai.APIPromise<T> {
// Prefer the public .then; fall back to _thenUnwrap only if present (v4/v5 APIPromise).
const apiPromise: any = promise as any;
const chain =
typeof apiPromise._thenUnwrap === "function"
? apiPromise._thenUnwrap.bind(apiPromise)
: apiPromise.then.bind(apiPromise);
return chain((result: any) => {
if (version === "v3") {
🤖 Prompt for AI Agents
In packages/instrumentation-openai/src/instrumentation.ts around lines 604 to
611, the code calls the non-public promise helper _thenUnwrap which may not
exist on v3 APIPromise; change the wrapper to first check for
promise._thenUnwrap and use it if present, otherwise fall back to promise.then,
ensuring the same callback handling and returned APIPromise shape so
instrumentation works with v3 and future versions.

@nirga
Copy link
Member

nirga commented Aug 14, 2025

Yes 🙈

@hmnzr hmnzr closed this Aug 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support OpenAI SDK v5
4 participants